﻿using System;
using System.IO;
using System.Text;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using Newtonsoft.Json.Linq;
using TrinityAPI.Base;
using TrinityAPI.Base.Tools;
using TrinityAPI.Base.Models;

namespace Express.JingDong
{
    public class GetWaybill : IAction
    {
        private string courierCode;

        public JToken Invoke(JObject dataset, params JToken[] args)
        {
            var request = dataset.GetJsonObject("request");
            var constant = dataset.GetJsonObject("constant");
            var courierInfo = constant.GetNecessaryJsonObject("courierInfo", "constant");
            var emailConfig = constant.GetJsonObject("emailAlter");

            courierCode = request.GetNecessaryJsonObjectStringValue("courierCode", "request");
            var config = courierInfo.GetNecessaryJsonObject(courierCode, "constant.courierInfo");

            return CreateWaybill(request, config, emailConfig);
        }

        public JObject CreateWaybill(JObject request, JObject config, JObject emailConfig)
        {
            string path = string.IsNullOrWhiteSpace(courierCode) ? null : string.Format("constant.courierInfo.{0}", courierCode);
            string url = config.GetNecessaryJsonObjectStringValue("url", path);
            string appkey = config.GetNecessaryJsonObjectStringValue("appkey", path);
            string appsecret = config.GetNecessaryJsonObjectStringValue("appsecret", path);
            string accessTokenPath = config.GetNecessaryJsonObjectStringValue("accesstokenpath", path);
            string customerCode = config.GetNecessaryJsonObjectStringValue("customercode", path);
            string expressType = config.GetJsonObjectStringValue("expresstype", "ed-m-0001");
            int payMethod = config.GetJsonObjectIntValue("paymethod", 3);
            string method = config.GetJsonObjectStringValue("createmethod", "/ecap/v1/orders/create");
            var timeout = config.GetJsonObjectIntValue("timeout", 30000);
            var proxy = config.GetJsonObjectValue("proxy");
            string orderId = request.GetNecessaryJsonObjectStringValue("orderid");
            string deliverOrderId = request.GetJsonObjectStringValue("deliverOrderId", orderId);

            var cargoes = new JArray();
            var items = request.GetJsonObjectList<JObject>("cargoes");
            if (items != null)
            {
                foreach (var item in items)
                {
                    cargoes.Add(new JObject() {
                        { "name", item.GetJsonObjectStringValue("sku") },
                        { "quantity", item.GetJsonObjectIntValue("qty") },
                        { "weight", 1 },
                        { "volume", 100 }
                    });
                }
            }

            JArray paramArray = new JArray();
            paramArray.Add(new JObject()
            {
                { "orderId", deliverOrderId },
                { "settleType", payMethod },
                { "orderOrigin", 1 },
                { "customerCode", customerCode },
                { "cargoes", cargoes },
                { "productsReq", new JObject()
                    {
                        { "productCode", expressType }
                    }
                },
                { "senderContact", new JObject()
                    {
                        { "name", request.GetJsonObjectStringValue("from_contact") },
                        { "phone", request.GetJsonObjectStringValue("from_phone") },
                        { "mobile", request.GetJsonObjectStringValue("from_mobile") },
                        { "fullAddress", request.GetJsonObjectStringValue("from_address") }
                    }
                },
                { "receiverContact", new JObject()
                    {
                        { "name", request.GetJsonObjectStringValue("to_contact") },
                        { "phone", request.GetJsonObjectStringValue("to_phone") },
                        { "mobile", request.GetJsonObjectStringValue("to_mobile") },
                        { "fullAddress", request.GetJsonObjectStringValue("to_address") }
                    }
                }
            });
            string param = paramArray.ToString(Newtonsoft.Json.Formatting.None);
            string accessToken = GetToken(config, emailConfig);
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string content = string.Format("{0}access_token{1}app_key{2}method{3}param_json{4}timestamp{5}v2.0{0}", appsecret, accessToken, appkey, method, param, timestamp);
            string sign = Utils.MD5(content, Encoding.UTF8, true);
            url = string.Format("{0}{1}?app_key={2}&access_token={3}&timestamp={4}&v=2.0&LOP-DN=ECAP&sign={5}", url, method, appkey, accessToken, timestamp, sign);
            
            try
            {
                LogHelper.Info("url: " + url, "JDLApiLog");
                LogHelper.Info("request: " + param, "JDLApiLog");
                string result = HttpHelper.HttpWebRequest(url, param, "POST", timeout, null, proxy?.ToString());
                LogHelper.Info("response: " + result, "JDLApiLog");

                var apiResponse = JSONHelper.JsonToJObject(result);

                int code = apiResponse.GetJsonObjectIntValue("code");

                if (code == 0)
                {
                    request["accessToken"] = accessToken;

                    JObject response = new JObject();
                    response["orderId"] = orderId;
                    response["waybillCode"] = apiResponse.GetJsonObject("data").GetJsonObjectStringValue("waybillCode");
                    response["waybillFilePath"] = CreateWaybillPDF(request, response, config, emailConfig).GetJsonObjectStringValue("waybillFilePath");
                    return response;
                }
                else
                {
                    string msg = apiResponse.GetJsonObjectStringValue("msg");
                    string sub_msg = apiResponse.GetJsonObjectStringValue("subMsg");
                    throw ExceptionHelper.GenException("@E210000002", msg + (string.IsNullOrWhiteSpace(sub_msg) ? "" : "-" + sub_msg));
                }
            }
            catch (BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Error("JingDong CreateWaybill fail", ex, "JDLApiLog");
                throw new Exception("@E210000001");
            }
        }

        public JObject CreateWaybillPDF(JObject request, JObject waybill, JObject config, JObject emailConfig)
        {
            string path = string.IsNullOrWhiteSpace(courierCode) ? null : string.Format("constant.courierInfo.{0}", courierCode);
            string url = config.GetNecessaryJsonObjectStringValue("url", path);
            string appkey = config.GetNecessaryJsonObjectStringValue("appkey", path);
            string appsecret = config.GetNecessaryJsonObjectStringValue("appsecret", path);
            string accessTokenPath = config.GetNecessaryJsonObjectStringValue("accesstokenpath", path);
            string customerCode = config.GetNecessaryJsonObjectStringValue("customercode", path);
            string waybillFileDir = config.GetNecessaryJsonObjectStringValue("waybillfiledir", path);
            string waybillFileUrl = config.GetJsonObjectStringValue("waybillfileurl");
            string templateCode = config.GetJsonObjectStringValue("templateCode", "jdkd100x150");
            string method = config.GetJsonObjectStringValue("printmethod", "/cloud/print/render");
            var timeout = config.GetJsonObjectIntValue("timeout", 30000);
            var proxy = config.GetJsonObjectValue("proxy");

            int packageNo = request.GetJsonObjectIntValue("package_no");
            int packageTotal = request.GetJsonObjectIntValue("package_total");
            string ecomOrderId = request.GetJsonObjectStringValue("ecom_orderid");
            string orderId = request.GetNecessaryJsonObjectStringValue("orderid");
            string deliverOrderId = request.GetJsonObjectStringValue("deliverOrderId", orderId);
            string accessToken = request.GetJsonObjectStringValue("accessToken");

            string waybillCode = waybill.GetNecessaryJsonObjectStringValue("waybillCode");

            string cargoStr = "";
            var items = request.GetJsonObjectList<JObject>("cargoes");
            if (items != null)
            {
                foreach (var item in items)
                {
                    cargoStr += string.Format("{0}*{1};", item.GetJsonObjectStringValue("sku"), item.GetJsonObjectIntValue("qty"));
                }
            }
            cargoStr = cargoStr + ecomOrderId;

            // 在remark显示(多包裹)
            if (packageTotal > 1 && packageNo > 0)
            {
                cargoStr = cargoStr + string.Format("({0}/{1})", packageNo, packageTotal);
            }

            JArray printData = new JArray();
            printData.Add(new JObject()
            {
                { "carrierCode", "JD" },
                { "billCodeType", "waybillCode" },
                { "billCodeValue", waybillCode },
                { "orderNumber", deliverOrderId },
                { "scene ", 4 },
                { "customerPrintData", new JObject()
                    {
                        { "productCode", "ed-m-0001" },
                        { "businessOrderId", ecomOrderId },
                        { "senderName", request.GetJsonObjectStringValue("from_contact") },
                        { "senderMobile", request.GetJsonObjectStringValue("from_mobile") },
                        { "senderAddress", request.GetJsonObjectStringValue("from_address") },
                        { "receiverName", request.GetJsonObjectStringValue("to_contact") },
                        { "receiverMobile", request.GetJsonObjectStringValue("to_mobile") },
                        { "receiverAddress", request.GetJsonObjectStringValue("to_address") },
                        { "remark", cargoStr },
                        { "weight", 1 },
                        { "packageCount", 1 },
                        { "settleType ", 0 }
                    }
                }
            });

            JArray paramArray = new JArray();
            paramArray.Add(new JObject()
            {
                { "taskId", Guid.NewGuid().ToString() },
                { "templateCode", templateCode },
                { "customerCode", customerCode },
                { "operator", customerCode },
                { "printData", printData },
                { "outputConfig", new JObject()
                    {
                        { "outputType", 1 },
                        { "dataFormat", 2 },
                        { "fileFormat", 1 }
                    }
                }
            });

            string param = paramArray.ToString(Newtonsoft.Json.Formatting.None);
            if (string.IsNullOrWhiteSpace(accessToken))
                accessToken = GetToken(config, emailConfig);
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string content = string.Format("{0}access_token{1}app_key{2}method{3}param_json{4}timestamp{5}v2.0{0}", appsecret, accessToken, appkey, method, param, timestamp);
            string sign = Utils.MD5(content, Encoding.UTF8, true);
            url = string.Format("{0}{1}?app_key={2}&access_token={3}&timestamp={4}&v=2.0&LOP-DN=jdcloudprint&sign={5}", url, method, appkey, accessToken, timestamp, sign);

            try
            {
                LogHelper.Info("url: " + url, "JDLApiLog");
                LogHelper.Info("request: " + param, "JDLApiLog");
                string result = HttpHelper.HttpWebRequest(url, param, "POST", timeout, null, proxy?.ToString());
                LogHelper.Info("response: " + result, "JDLApiLog");

                var apiResponse = JSONHelper.JsonToJObject(result);

                int code = apiResponse.GetJsonObjectIntValue("code");

                if (code == 1000)
                {
                    var results = apiResponse.GetJsonObjectList<JObject>("result");
                    if (results == null || results.Count == 0)
                        throw new Exception("没有面单数据");
                    string base64data = results[0].GetJsonObjectStringValue("base64");
                    if (string.IsNullOrWhiteSpace(base64data))
                        throw new Exception("没有面单数据");

                    byte[] bytes = Convert.FromBase64String(base64data);

                    string fileName = waybillCode + ".pdf";
                    string filePath = waybillFileDir.StartsWith(@"\\") ? waybillFileDir : Utils.GetMapPath(waybillFileDir);
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    string fileFullPath = filePath + "\\" + fileName;
                    FileStream fs = new FileStream(fileFullPath, FileMode.Create);
                    fs.Write(bytes, 0, bytes.Length);
                    fs.Close();

                    using (PdfDocument document = new PdfDocument())
                    {
                        PdfPage page = document.AddPage();
                        page.Size = PdfSharp.PageSize.A4;
                        page.Orientation = PdfSharp.PageOrientation.Landscape;

                        // Get an XGraphics object for drawing
                        XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsUnit.Millimeter);

                        using (XImage image = XImage.FromFile(fileFullPath))
                        {
                            gfx.DrawImage(image, 21, 21, 100, 150);
                            gfx.DrawImage(image, 176, 21, 100, 150);
                        }
                        byte[] logoBytes = Convert.FromBase64String(GetLogoString());
                        using(var logoMs = new MemoryStream(logoBytes))
                        using (XImage image = XImage.FromStream(logoMs))
                        {
                            gfx.DrawImage(image, 24, 25, 20, 3.32);
                            gfx.DrawImage(image, 179, 25, 20, 3.32);
                        }
                        document.Save(fileFullPath);
                    }

                    if (!string.IsNullOrWhiteSpace(waybillFileUrl) && !waybillFileUrl.EndsWith("/"))
                        waybillFileUrl += "/";

                    var response = new JObject();
                    response["orderId"] = orderId;
                    response["waybillCode"] = waybillCode;
                    response["waybillFilePath"] = fileName;
                    if (!string.IsNullOrWhiteSpace(waybillFileUrl))
                        response["waybillFileURL"] = waybillFileUrl + fileName;
                    return response;
                }
                else
                {
                    string msg = apiResponse.GetJsonObjectStringValue("msg");
                    throw ExceptionHelper.GenException("@E210000004", msg);
                }
            }
            catch (BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Error("JingDong CreateWaybillPDF fail", ex, "JDLApiLog");
                throw new Exception("@E210000003");
            }
        }

        private string GetLogoString()
        {
            return "iVBORw0KGgoAAAANSUhEUgAAAfQAAABTCAYAAABpuPVoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF42lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIzLTA2LTIwVDE5OjE5OjUyKzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMy0wOS0xNFQxNToyNDoxMiswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMy0wOS0xNFQxNToyNDoxMiswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpjNGJkNDQyZC04MzY3LWM5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";
        }

        private static string GetToken(JObject config, JObject emailConfig)
        {
            string accessTokenPath = config.GetNecessaryJsonObjectStringValue("accesstokenpath");
            int hours = config.GetJsonObjectIntValue("accessAuthBeforeHours");

            if (hours <= 0)
                hours = 216; //9天后到期，发邮件提醒

            var accessTokenInfo = JSONHelper.JsonToJObject(Utils.LoadTextFile(Utils.GetMapPath(accessTokenPath)));
            if (accessTokenInfo == null)
            {
                SendAlertMessage(emailConfig);
                throw new Exception("@E210000005");
            }

            var now = DateTime.Now;
            var expireTime = DateTime.MaxValue;
            DateTime.TryParse(accessTokenInfo.GetJsonObjectStringValue("accessExpire"), out expireTime);
            var expireHours = (expireTime - now).TotalHours;
            if (expireHours <= hours)
            {
                SendAlertMessage(emailConfig, expireHours);
                if (expireHours < 0)
                    throw new Exception("@E210000006");
            }

            return accessTokenInfo.GetJsonObjectStringValue("accessToken");
        }

        private static void SendAlertMessage(JObject config, double? hours = null)
        {
            if (config == null)
                return;
            string host = config.GetJsonObjectStringValue("host");
            string username = config.GetJsonObjectStringValue("username");
            string password = config.GetJsonObjectStringValue("password");
            string sender = config.GetJsonObjectStringValue("sender");
            string receiver = config.GetJsonObjectStringValue("receiver");
            string cc = config.GetJsonObjectStringValue("cc");
            string bcc = config.GetJsonObjectStringValue("bcc");
            if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(sender) || string.IsNullOrWhiteSpace(receiver))
                return;
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(o =>
            {
                try
                {
                    string subject = "京东物流请求授权";
                    string message = "京东物流未授权。请授权：";

                    if (hours.HasValue)
                    {
                        string flag = hours > 0 ? "将在" + DateTime.Now.AddHours(hours.Value).ToString("yyyy-MM-dd HH:mm") : "已经";
                        subject = string.Format("京东物流授权{0}过期", hours.Value > 0 ? "即将" : "已经");
                        message = string.Format("京东物流授权{0}过期。请及时重新授权：", flag);
                    }

                    string body = "<style>/*TableHead*/#table-5theadth{background-color:rgb(156,186,95);color:#fff;border-bottom-width:0;}/*HeadingandColumnStyle*/#table-5tr,#table-5th,#table-5td{border-width:1px;border-style:solid;border-color:rgb(156,186,95);}/*Paddingandfontstyle*/#table-5th{padding:5px10px;font-size:12px;font-family:Verdana;font-weight:bold;}#table-5td{padding:5px10px;}#table-5tabletd{white-space:nowrap;font-size:12px;font-family:Verdana;border:none;}body{font-size:15px;font-family:Verdana;font-weight:100;}</style><body>Dear Team:<br/><br/>" + message + "<br/><br/>授权网址：<br/>https://oauth.jdl.com/oauth/authorize?client_id=9B70586B1FBE21893F36B412CAA5A9A8&redirect_uri=https%3A%2F%2Fgoapi.trinitybrands.com.cn%2Ftrinityapi%2Fexpress.jdl%2Fv1.0%2FAccessAuth&response_type=code<br/><br/><br/>(这是系统生成的电子邮件，请不要回复。)<br/><br/></body>";

                    Utils.SendEmail(subject, body, receiver, sender, host, username, password, null, true, cc, bcc);
                }
                catch (Exception ex)
                {
                    LogHelper.Error("Send jdl authorization email error", ex);
                }
            }));
        }
    }
}
